from flask import Flask
from flask_restful import reqparse, abort, Api, Resource
import logging
from logging.handlers import RotatingFileHandler

from tqsdk import TqApi, TqAuth
import datetime
import threading
import time
import redis
import json

app = Flask(__name__)
api = Api(app)

# 创建Redis连接
red = redis.Redis(host='localhost', port=6379, db=0)
thread_event = threading.Event()

klinesTest = None
# 配置日志记录
# handler = RotatingFileHandler('app.log', maxBytes=10000, backupCount=1)
# handler.setLevel(logging.DEBUG)
 
# formatter = logging.Formatter('%(asctime)s %(levelname)s: %(message)s [in %(pathname)s:%(lineno)d]')
# handler.setFormatter(formatter)
 
# app.logger.addHandler(handler)

####### log #######

# app.config['PROPAGATE_EXCEPTIONS'] = False  
# 设置是否传递异常 , 如果为True, 则flask运行中的错误会显示到网页中, 如果为False, 则会输出到文件中

class RequestFormatter(logging.Formatter):  # 自定义格式化类
    def format(self, record):
        """每次生成日志时都会调用, 该方法主要用于设置自定义的日志信息
        :param record 日志信息"""
        record.url = request.url  # 获取请求的url
        record.remote_addr = request.remote_addr  # 获取客户端的ip

        return super().format(record)  # 执行父类的默认操作

# flask中提供了两个日志  1> werkzeug 记录web应用运行中出现的错误  2> flask.app  给开发者预留的日志
# flask中的运行错误也会记录到flask.app的日志中
def create_logger():
    """配置flask日志"""
    # 创建flask.app日志器
    # flask_logger = logging.getLogger('flask.app')
    # flask_logger = logging.getLogger(__name__)

    # 设置全局级别
    # flask_logger.setLevel('DEBUG')

    # # 创建控制台处理器
    # console_handler = logging.StreamHandler()

    # # 给处理器设置输出格式
    # console_formatter = logging.Formatter(fmt='%(name)s %(levelname)s %(pathname)s %(lineno)d %(message)s')
    # console_handler.setFormatter(console_formatter)

    # # 日志器添加处理器
    # flask_logger.addHandler(console_handler)

    # 创建文件处理器
    # file_handler = RotatingFileHandler(filename='aaflask.log', maxBytes=100 * 1024 * 1024, backupCount=10,encoding='utf-8')  # 转存文件处理器  当达到限定的文件大小时, 可以将日志转存到其他文件中
    file_handler = RotatingFileHandler('app.log', maxBytes=1024*1024, backupCount=1,encoding='utf-8')
    # 给处理器设置输出格式
    # file_formatter = RequestFormatter(fmt='[%(asctime)s] %(remote_addr)s requested %(url)s %(name)s %(levelname)s %(pathname)s %(lineno)d %(message)s')
    file_formatter = logging.Formatter(fmt='[%(asctime)s] %(name)s %(levelname)s %(pathname)s %(lineno)d %(message)s')
    file_handler.setFormatter(file_formatter)
    # 单独设置文件处理器的日志级别 DEBUG
    #file_handler.setLevel('WARN')
    file_handler.setLevel(logging.DEBUG)

    # 日志器添加处理器
    # flask_logger.addHandler(file_handler)
    app.logger.addHandler(file_handler)

####### log #######

################TQ#############
def start_runner():
    def start_loop():
        api = TqApi(auth=TqAuth("houzx910", "houzx289310"))
        klinesTest = api.get_kline_serial("DCE.c2401", 30)
        # app.logger.info("TQ test")
        while True:
            api.wait_update()
            if api.is_changing(klines11.iloc[-1], "datetime"):
                print("11新线", datetime.datetime.fromtimestamp(klines11.iloc[-1]["datetime"] / 1e9))
                app.logger.info("11新线: %s", datetime.datetime.fromtimestamp(klines11.iloc[-1]["datetime"] / 1e9))
            if api.is_changing(klines11.iloc[-1], "close"):
                print("11变化", datetime.datetime.fromtimestamp(klines11.iloc[-1]["datetime"] / 1e9), klines11.close.iloc[-1])
                app.logger.info("11变化: %s %s", datetime.datetime.fromtimestamp(klines11.iloc[-1]["datetime"] / 1e9), klines11.close.iloc[-1])
                app.logger.info("11变化: %s %s", datetime.datetime.fromtimestamp(klines11.iloc[-1]["datetime"] / 1e9), klines11.close.iloc[-1])
        api.close()

    thread = threading.Thread(target=start_loop)
    thread.start()


def start_runner_test():
    def start_loop():
        while True:
            time.sleep(3)
            app.logger.info("TTT")

    thread = threading.Thread(target=start_loop)
    thread.start()
################TQ#############
TODOS = {
    'todo1': {'task': 'build an API'},
    'todo2': {'task': '?????'},
    'todo3': {'task': 'profit!'},
}


def abort_if_todo_doesnt_exist(todo_id):
    if todo_id not in TODOS:
        app.logger.error('this is a error')
        app.logger.info("11")
        app.logger.info("Todo {} doesn't exist".format(todo_id))
        abort(404, message="Todo {} doesn't exist".format(todo_id))

parser = reqparse.RequestParser()
parser.add_argument('task')


# Todo
# shows a single todo item and lets you delete a todo item
class Todo(Resource):
    def get(self, todo_id):
        try:
            app.logger.info('Processing request for index page')
            app.logger.info(TODOS)
            # red.publish('redislife', json.dumps(TODOS))
            # thread_event.clear()
            abort_if_todo_doesnt_exist(todo_id)
            return TODOS[todo_id]
        except Exception as error:
            return str(error)

    def delete(self, todo_id):
        abort_if_todo_doesnt_exist(todo_id)
        del TODOS[todo_id]
        return '', 204

    def put(self, todo_id):
        args = parser.parse_args()
        task = {'task': args['task']}
        TODOS[todo_id] = task
        return task, 201


# TodoList
# shows a list of all todos, and lets you POST to add new tasks
class TodoList(Resource):
    def get(self):
        try:
            # thread_event.set()
            # thread = threading.Thread(target=start_runner_test)
            # thread.start()
            return TODOS
        except Exception as error:
            return str(error)

    def post(self):
        args = parser.parse_args()
        todo_id = int(max(TODOS.keys()).lstrip('todo')) + 1
        todo_id = 'todo%i' % todo_id
        TODOS[todo_id] = {'task': args['task']}
        return TODOS[todo_id], 201

##
## Actually setup the Api resource routing here
##
api.add_resource(TodoList, '/todos')
api.add_resource(Todo, '/todos/<todo_id>')
##############restful########

if __name__ == '__main__':
    create_logger()
    # start_runner()
    # start_runner_test()
    app.run(debug=True)